﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using System.Web.Mvc;
using XRM.Sag.Utils.Helpers;
using XRM.Sag.Utils.Logger;
using XRM.Security.Api.EipInteraction;
using XRM.Security.DataAccess;
using XRM.Security.DataAccess.Enums;
using XRM.Security.DataAccess.Repositories.Impl;

namespace XRM.Security.Api.Controllers
{
    [RequireHttps]
    public class CertificateServiceController : ApiController
    {
        public const String ServiceName = "Получение сведений о выпущенных сертификатах";
        public const String ServiceVersion = "1.0.0";

        private ILogger _logger;
        public ILogger Logger
        {
            get
            {
                return _logger ?? ( _logger = new Logger() );
            }
            set
            {
                _logger = value;
            }
        }

        public IEipService EipService { get; set; }

        public CertificateServiceController()
        {
            EipService = new EipService();
        }

        [System.Web.Http.HttpGet]
        public CertificatesType GetCertificateList( DateTime start, DateTime? end = null )
        {
            var participantCert = Request.GetClientCertificate();
            if (participantCert == null)
            {
                throw new HttpResponseException( HttpStatusCode.BadRequest );
            }
            var participantName = ConfigurationManager.AppSettings["ParticipantName"];
            if ( !EipService.Authorize( participantCert, participantName, ServiceName, ServiceVersion, "GetCertificateList" ) )
            {
                throw new HttpResponseException(HttpStatusCode.Forbidden);
            }
            var result = new CertificatesType
                {
                    Start = start,
                    ResponseDateTime = DateTime.Now
                };
            using (var dataManager = new DataManager())
            {
                var certificates = dataManager.CertRegisterRepository.GetAll( s => s.UploadDate >= start && s.UserRegister.Status == (int)UserStatus.Work);
                if (end.HasValue)
                {
                    var uploadEndDate = end.Value.AddDays(1);
                    certificates = certificates.Where( s => s.UploadDate < uploadEndDate );
                    result.End = end.Value;
                    result.EndSpecified = true;
                }
                var certList = certificates.OrderBy( s => s.UploadDate )
                    .Select( s => new {s.UserRegisterId, s.FromDate, s.FileData, s.Thumbprint, s.UserRegister.FirstName, s.UserRegister.LastName, s.UserRegister.MotherName})
                    .ToList();
                var userIds = certList.Select( s => s.UserRegisterId ).Distinct().ToList();
                var certThumbprints = dataManager.CertRegisterRepository.GetAll( s => userIds.Contains( s.UserRegisterId ) )
                    .Select( s => new {s.UserRegisterId, s.Thumbprint, s.FromDate}).ToList();

                var certTypeList = new List<CertificateType>();
                foreach (var cert in certList)
                {
                    var prevThumbprints = certThumbprints.Where( s => s.UserRegisterId == cert.UserRegisterId && s.FromDate < cert.FromDate )
                        .OrderBy( s => s.FromDate )
                        .Select( s => ConvertersHelper.HexStringToByteArray(s.Thumbprint) ).ToArray();
                    certTypeList.Add( new CertificateType
                        {
                                Content = cert.FileData,
                                FirstName = cert.FirstName,
                                LastName = cert.LastName,
                                MiddleName = cert.MotherName,
                                PreviousCertificateThumbprint = prevThumbprints
                        });
                }
                Log(start, end, certList.Select( s => s.Thumbprint));
                result.Certificate = certTypeList.ToArray();
            }
            return result;
        }

        private void Log(DateTime start, DateTime? end, IEnumerable<string> certThumbrints)
        {
            var sb = new StringBuilder();
            sb.Append( String.Format( "Period: start={0:dd.MM.yyyy}", start ) );
            if ( end.HasValue )
            {
                sb.Append( String.Format(", end={0:dd.MM.yyyy}", end.Value ) );
            }
            sb.AppendLine();
            sb.AppendLine( String.Format( "Certificates: {0}", String.Join( "; ", certThumbrints ) ) );
            Logger.Write(sb.ToString());
        }
    }
}
